package cn.demoncat.util.word.constant;

import cn.demoncat.util.io.IoUtil;
import cn.demoncat.util.lang.entity.data.DoublePoint;
import cn.demoncat.util.lang.entity.data.IntegerPoint;
import cn.demoncat.util.lang.entity.LinkedMapSs;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Word生成常量
 *
 * @author 延晓磊
 * @since 2021年04月09日
 */
public class WordGenConstant {


    /**
     * 文档样式
     *
     * 1、创建样式模板文档：/docx/style.docx
     * 2、调用 WordGenUtil.checkStyles() 检查样式设置
     * 3、通过样式设置的 w:styleId 获取样式ID（样式映射）
     * 4、通过 paragraph.setStyle(styleId) 设置段落样式
     *
     * @author 延晓磊
     * @since 2021年04月10日
     */
    public interface Style{

        /**
         * 正文
         */
        String NORMAL = "10";
        /**
         * 标题1
         */
        String TITLE_1 = "11";
        /**
         * 标题2
         */
        String TITLE_2 = "12";
        /**
         * 标题3
         */
        String TITLE_3 = "13";
        /**
         * 标题4
         */
        String TITLE_4 = "14";
        /**
         * 标题5
         */
        String TITLE_5 = "15";


        /**
         * 名称映射
         */
        LinkedMapSs NAME_MAP = LinkedMapSs.getInstance(NORMAL,"正文",TITLE_1,"标题1",TITLE_2,"标题2",TITLE_3,"标题3",TITLE_4,"标题4",TITLE_5,"标题5");

        /**
         * 样式id映射（通过样式name获取）
         */
        LinkedMapSs STYLE_ID_MAP = LinkedMapSs.getInstance();
        /**
         * 样式name映射
         */
        LinkedMapSs STYLE_NAME_MAP = LinkedMapSs.getInstance(NORMAL,"Normal",TITLE_1,"heading 1",TITLE_2,"heading 2",TITLE_3,"heading 3",TITLE_4,"heading 4",TITLE_5,"heading 5");

        /**
         * CSS样式：像素
         */
        LinkedHashMap<String, LinkedMapSs> CSS_MAP = new LinkedHashMap<String,LinkedMapSs>(){{
            put(NORMAL,LinkedMapSs.getInstance("font-family","仿宋","font-size","14px","line-height","14px"));
            put(TITLE_1,LinkedMapSs.getInstance("font-family","微软雅黑","font-size","34px","line-height","34px","font-weight","bold","padding-top","22px","padding-bottom","20px"));
            put(TITLE_2,LinkedMapSs.getInstance("font-family","微软雅黑","font-size","29px","line-height","29px","font-weight","bold","padding-top","17px","padding-bottom","17px"));
            put(TITLE_3,LinkedMapSs.getInstance("font-family","微软雅黑","font-size","21px","line-height","21px","font-weight","bold","padding-top","17px","padding-bottom","17px"));
            put(TITLE_4,LinkedMapSs.getInstance("font-family","微软雅黑","font-size","18px","line-height","18px","font-weight","bold","padding-top","18px","padding-bottom","19px"));
            put(TITLE_5,LinkedMapSs.getInstance("font-family","微软雅黑","font-size","14px","line-height","14px","font-weight","bold","padding-top","18px","padding-bottom","19px"));
        }};

        /**
         * 模板文档
         */
        String TEMPLATE_DOCX = "docx/style.docx";
        /**
         * 模板样式
         */
        CTStyles TEMPLATE_STYLE = getWordStyle();

    }

    /**
     * 字号
     *
     * @author 延晓磊
     * @since 2021年04月10日
     */
    public interface FontSize{
        /**
         * 1号
         */
        String NUMBER_1 = "1";
        /**
         * 2号
         */
        String NUMBER_2 = "2";
        /**
         * 3号
         */
        String NUMBER_3 = "3";
        /**
         * 4号
         */
        String NUMBER_4 = "4";
        /**
         * 5号
         */
        String NUMBER_5 = "5";

        /**
         * 名称映射
         */
        LinkedMapSs NAME_MAP = LinkedMapSs.getInstance(NUMBER_1,"一号",NUMBER_2,"二号",NUMBER_3,"三号",NUMBER_4,"四号",NUMBER_5,"五号");

        /**
         * 字号映射：字号 VS pt（point，1磅=0.376毫米=0.1776英寸）
         */
        HashMap<String,Integer> PT_MAP = new HashMap<String,Integer>(){{
            put(NUMBER_1,26);
            put(NUMBER_2,22);
            put(NUMBER_3,16);
            put(NUMBER_4,14);
            put(NUMBER_5,11);
        }};

        /**
         * 字号映射：字号 VS px（pixel，1像素=0.75pt）
         */
        HashMap<String,Integer> PX_MAP = new HashMap<String,Integer>(){{
            put(NUMBER_1,34);
            put(NUMBER_2,29);
            put(NUMBER_3,21);
            put(NUMBER_4,18);
            put(NUMBER_5,14);
        }};

    }

    /**
     * 纸张
     *
     * @author 延晓磊
     * @since 2021年04月10日
     */
    public interface Paper{

        String A3 = "A3";
        String A4 = "A4";
        String A5 = "A5";

        /**
         * 映射
         */
        interface Map{
            /**
             * 缇 (1/20Pt)
             */
            HashMap<String, IntegerPoint> SIZE = new HashMap<String,IntegerPoint>(){{
                put(A3,new IntegerPoint(16838, 23811));
                put(A4,new IntegerPoint(11906, 16838));
                put(A5,new IntegerPoint(8391, 11906));
            }};
            /**
             * 毫米（Word标准）
             */
            HashMap<String, IntegerPoint> SCALE = new HashMap<String,IntegerPoint>(){{
                put(A3,new IntegerPoint(297, 420));
                put(A4,new IntegerPoint(210, 297));
                put(A5,new IntegerPoint(148, 210));
            }};
            /**
             * 像素（根据字号比例换算）
             */
            HashMap<String, IntegerPoint> PX = new HashMap<String,IntegerPoint>(){{
                put(A3,new IntegerPoint(1121, 1586));
                put(A4,new IntegerPoint(793, 1121));
                put(A5,new IntegerPoint(558, 793));
            }};
            /**
             * 内容 - 缇 (1/20Pt)
             */
            HashMap<String, IntegerPoint> CONTENT_SIZE = new HashMap<String,IntegerPoint>(){{
                put(A3,new IntegerPoint(13244, 20931));
                put(A4,new IntegerPoint(8312, 13958));
                put(A5,new IntegerPoint(4797, 9026));
            }};
        }

        /**
         * 页边距
         */
        interface Padding{
            /**
             * 缇 (1/20Pt)
             */
            IntegerPoint SIZE = new IntegerPoint(1797, 1440);

            /**
             * 毫米（Word标准）
             */
            DoublePoint SCALE = new DoublePoint(31.7, 25.4);

            /**
             * 像素（以A4比例换算）
             */
            IntegerPoint PX = new IntegerPoint(119, 169);
        }

        /**
         * CSS样式：像素
         */
        HashMap<String, LinkedMapSs> CSS_MAP = new HashMap<String,LinkedMapSs>(){{
            put(A3,LinkedMapSs.getInstance("width","1121px","height","1586px","padding","169px 119px"));
            put(A4,LinkedMapSs.getInstance("width","793px","height","1121px","padding","169px 119px"));
            put(A5,LinkedMapSs.getInstance("width","558px","height","793px","padding","169px 119px"));
        }};
    }

    /**
     * 水平对齐方式
     *
     * @author 延晓磊
     * @since 2021年04月10日
     */
    public interface Align{

        String LEFT = "1";
        String CENTER = "2";
        String RIGHT = "3";
        String BOTH = "4";

        /**
         * 名称映射
         */
        LinkedMapSs NAME_MAP = LinkedMapSs.getInstance(LEFT,"左对齐",CENTER,"居中对齐",RIGHT,"右对齐",BOTH,"两端对齐");

        /**
         * 值映射
         */
        HashMap<String,ParagraphAlignment> VALUE_MAP = new HashMap<String,ParagraphAlignment>(){{
            put(LEFT, ParagraphAlignment.LEFT);
            put(CENTER,ParagraphAlignment.CENTER);
            put(RIGHT,ParagraphAlignment.RIGHT);
            put(BOTH,ParagraphAlignment.BOTH);
        }};

    }

    /**
     * 垂直对齐方式
     *
     * @author 延晓磊
     * @since 2021年04月10日
     */
    public interface VerticalAlign{

        String TOP = "1";
        String MIDDLE = "2";
        String BOTTOM = "3";

        /**
         * 名称映射
         */
        LinkedMapSs NAME_MAP = LinkedMapSs.getInstance(TOP,"顶对齐",MIDDLE,"居中对齐",BOTTOM,"底对齐");

        /**
         * 值映射
         */
        HashMap<String,String> VALUE_MAP = new HashMap<String,String>(){{
            put(TOP, "superscript");
            put(MIDDLE,"baseline");
            put(BOTTOM,"subscript");
        }};

    }

    /**
     * 数据断点
     *
     * @author 延晓磊
     * @since 2021年04月10日
     */
    public interface RunBreak{

        /**
         * 制表符
         */
        String TAB = "1";
        /**
         * 换行
         */
        String LINE = "2";
        /**
         * 换页
         */
        String PAGE = "3";

        /**
         * 名称映射
         */
        LinkedMapSs NAME_MAP = LinkedMapSs.getInstance(TAB,"制表符",LINE,"换行",PAGE,"换页");

    }

    /**
     * 内容类型
     *
     * @author 延晓磊
     * @since 2021年04月10日
     */
    public interface ContentType {

        /**
         * 段落
         */
        String PARAGRAPH = "10";
        /**
         * 表格
         */
        String TABLE = "11";


        /**
         * 名称映射
         */
        LinkedMapSs NAME_MAP = LinkedMapSs.getInstance(PARAGRAPH,"段落",TABLE,"表格");

        /**
         * 表格
         */
        interface Table{

            /**
             * 单元格偏移：[上，左，下，右]，默认100,0缇，即上下偏移5pt、6px
             */
            Integer[] CELL_MARGIN = new Integer[]{100,0,100,0};

            /**
             * 单元格CSS样式
             */
            LinkedMapSs CELL_CSS = LinkedMapSs.getInstance("padding", "6px 12px");
        }
    }

    /**
     * 数据类型
     *
     * @author 延晓磊
     * @since 2021年04月10日
     */
    public interface RunType{

        /**
         * 文本
         */
        String TEXT = "10";
        /**
         * 断点
         */
        String BREAK = "11";


        /**
         * 名称映射
         */
        LinkedMapSs NAME_MAP = LinkedMapSs.getInstance(TEXT,"文本",BREAK,"断点");
    }




    /**
     * 读取模板文档，获取样式
     *
     * @return
     *
     * @author 延晓磊
     *
     * @since 2017年8月11日
     */
    private static CTStyles getWordStyle() {
        // 读取模板文档，创建文档
        try (InputStream styleFile = IoUtil.getInputStreamByClassPath(Style.TEMPLATE_DOCX); XWPFDocument doc = new XWPFDocument(styleFile)) {
            // 获取模板样式
            CTStyles style = doc.getStyle();
            // 获取样式ID
            for (CTStyle ctStyle : style.getStyleList()) {
                for (Map.Entry<String, String> entry : Style.STYLE_NAME_MAP.entrySet()) {
                    if (entry.getValue().equalsIgnoreCase(ctStyle.getName().getVal())) {
                        Style.STYLE_ID_MAP.put(entry.getKey(), ctStyle.getStyleId());
                    }
                }
            }
            return style;
        } catch (XmlException | IOException e) {
            throw new RuntimeException("读取模板文档失败", e);
        }
    }
}
